﻿//! \file     winlog.c 
//! \brief    win模拟器log支持模块
//! \author   zhangjinxing
//! \par
//! (C) Copyright 杭州大仁科技有限公司
//! \version
//!

#include <windows.h>
#include <stdio.h>
#include <stdarg.h>


#define LOG_COLOR_RED 1

// **************************************************************************
// 内部数据成员

// 日志窗口
//
static char _LOG_acBuffer[5000];    // log字符串缓存
static HWND _LOG_hWnd = NULL;       // log窗口句柄
static int  _LOG_x0 = 0;
static int  _LOG_xsize = 500;
static int  _LOG_ysize = 200;

static const char acClassNameLog[] = "Log";

// **************************************************************************
// 内部函数

// 绘制log窗口
//
static void _LOG_Paint(HWND hWnd, HDC hdc) {
    RECT rt;
    int i, NumLines, WinSizeY;
    HANDLE hFont;
    SIZE size;
    char *s = _LOG_acBuffer;
    GetClientRect(hWnd, &rt);
    WinSizeY = rt.bottom - rt.top;
    if (*s == '\n')
        s++;
    hFont = GetStockObject(DEFAULT_GUI_FONT);
    SelectObject(hdc, hFont);
    GetTextExtentPoint32(hdc, "@", 1, &size);
    //
    // 计算行数量
    NumLines = 1;
    for (i = 0; *(s + i); i++)
        if (*(s + i) == '\n')
            NumLines++;
    //
    // 重新计算布局 总是按低端对齐
    rt.top += WinSizeY - NumLines * size.cy;
    while (*s) {
        SIZE SegSize;
        int Len;
        switch (*s) {
        case '\0':
            return;
        case LOG_COLOR_RED:
            SetTextColor(hdc, RGB(0, 0, 0xff));
            break;
        case '\n':
            rt.top += size.cy;
            rt.left = 0;
            s++;
        }
        if (*s == LOG_COLOR_RED) {
            SetTextColor(hdc, RGB(255, 0, 0));
            s++;
        }
        Len = 0;
        while (*(s + Len) && (*(s + Len) != '\n') && (*(s + Len) != LOG_COLOR_RED))
            Len++;
        DrawText(hdc, s, Len, &rt, DT_LEFT);
        GetTextExtentPoint32(hdc, s, Len, &SegSize);
        rt.left += SegSize.cx;
        SetTextColor(hdc, RGB(0, 0, 0));
        s += Len;
    }
}

// log窗口消息处理例程
//
static LRESULT CALLBACK _WndProcLog(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    PAINTSTRUCT ps;
    switch (message) {
        case WM_PAINT:
            HDC hdc = BeginPaint(hWnd, &ps);
            _LOG_Paint(hWnd, hdc);
            EndPaint(hWnd, &ps);
            break;
        case WM_DESTROY: 
            _LOG_hWnd = 0; 
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}


/*********************************************************************
*
*       _LOG_Clear
*/
void _LOG_Clear(void) {
    _LOG_acBuffer[0] = 0;
}

// 删除第一行记录
//
static void _LOG_DelFirstLine(void) {
    int i;
    for (i = 0; _LOG_acBuffer[i]; i++) {
        if (_LOG_acBuffer[i] == '\n') {
            strcpy(&_LOG_acBuffer[0], &_LOG_acBuffer[i + 1]);
            return;
        }
    }
}

// 添加日志记录的日志窗口尾部
//
static void _LOG_AddPlain(const char*s) {
    while (strlen(_LOG_acBuffer) + strlen(s) > sizeof(_LOG_acBuffer)) {
        _LOG_DelFirstLine();
    }
    strcpy(&_LOG_acBuffer[strlen(_LOG_acBuffer)], s);
    if (_LOG_hWnd) {
        InvalidateRect(_LOG_hWnd, NULL, TRUE);
    }
}

// 添加日志记录
// 
void __cdecl _LOG_Add(const char *format, ...) {
    char ac[200];
    va_list arglist;
    va_start(arglist, format);
    sprintf(ac, format,arglist);
    _LOG_AddPlain(ac);
};

/*********************************************************************
*
*       _LOG_AddRed
*/
void _LOG_AddRed(void) {
    char ac[200];
    ac[0] = LOG_COLOR_RED;
    ac[1] = 0;
    _LOG_Add(&ac[0]);
}

// 初始化log窗口
//
void WinLOG_Init(HINSTANCE hInst, HICON hIcon) {
    static char IsInitialized = 0;
    if (!IsInitialized) {
        WNDCLASSEX wcex;
        IsInitialized = 1;
        memset(&wcex, 0, sizeof(wcex));
        wcex.cbSize = sizeof(WNDCLASSEX);
        wcex.hInstance = hInst;
        wcex.style = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc = (WNDPROC)_WndProcLog;
        wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
        wcex.lpszMenuName = NULL;
        wcex.lpszClassName = acClassNameLog;
        wcex.hIcon = hIcon;
        wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
        RegisterClassEx(&wcex);
    }
}

// 创建log窗口
//
void WinLOG_Create(HINSTANCE hInst, HWND hWndParent, int y0) {
    if (_LOG_hWnd != 0)  // 该窗口只创建一个实例
        return;
    WinLOG_Init(hInst, 0);
    _LOG_hWnd = CreateWindow(acClassNameLog, "Log",
        WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
        | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CHILD | WS_CLIPSIBLINGS
        | WS_VISIBLE | WS_VSCROLL,
        _LOG_x0, y0, _LOG_xsize, _LOG_ysize,
        hWndParent, NULL, hInst, NULL);
}




